package com.yyhh.helpcall.utils;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.provider.CallLog;
import android.text.TextUtils;
import androidx.core.content.ContextCompat;
import com.google.gson.Gson;
import com.yyhh.helpcall.http.OkHttpUtils;
import com.yyhh.helpcall.http.bean.BaseResponse;
import com.yyhh.helpcall.http.bean.LastUpdateResponse;
import com.yyhh.helpcall.model.CallModel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

public class ScanCallLogUtils {

    public static final String[] columns = {
            CallLog.Calls.CACHED_NAME// 通话记录的联系人
            , CallLog.Calls.NUMBER// 通话记录的电话号码
            , CallLog.Calls.DATE// 通话记录的日期
            , CallLog.Calls.DURATION// 通话时长
            , CallLog.Calls.TYPE,// 通话类型
    };

    public static boolean flag = false;
    public static int taskCount = 0;
    public static int count = 0;

    /**
     * 上传通话记录
     */
    public static void uploadCallLogs(Context context) {
        if (ScanCallLogUtils.flag) return;
        ScanCallLogUtils.flag = true;

        OkHttpUtils.getInstance().getApi().getLastCallLogsTime(new HashMap<>())
                .observeOn(Schedulers.io())
                .map(new Function<BaseResponse<LastUpdateResponse>, Long>() {
                    @Override
                    public Long apply(BaseResponse<LastUpdateResponse> value) throws Exception {
                        //获取最新的时间戳
                        long last_timestamp = 0;
                        if (value.isSuccess() && !TextUtils.isEmpty(value.data.last_timestamp)) {
                            last_timestamp = Long.parseLong(value.data.last_timestamp);
                        }
                        NetLog.d("通话记录的最新时间戳 " + last_timestamp + ",当前线程 " + Thread.currentThread().getName());
                        return last_timestamp;
                    }
                })
                .observeOn(Schedulers.io())
                .map(new Function<Long, ArrayList<CallModel>>() {
                    @Override
                    public ArrayList<CallModel> apply(Long last_timestamp) throws Exception {
                        //扫描通话记录
                        List<CallModel> callModels = startScanCallLogs(context);

                        ArrayList<CallModel> filterResult = new ArrayList<>();
                        //匹配通话记录
                        for (int i = 0; i < callModels.size(); i++) {
                            CallModel callModel = callModels.get(i);
                            if (callModel.date > last_timestamp) {
                                filterResult.add(callModel);
                            }
                        }
                        NetLog.d("扫描到通话记录共" + callModels.size() + "条,匹配到" + filterResult.size() + "条，当前线程 " + Thread.currentThread().getName());

                        return filterResult;
                    }
                })
                .observeOn(Schedulers.io())
                .flatMap(new Function<ArrayList<CallModel>, ObservableSource<ArrayList<CallModel>>>() {
                    @Override
                    public ObservableSource<ArrayList<CallModel>> apply(ArrayList<CallModel> callModels) throws Exception {
                        //接口最大支持50条批量添加，所以进行这里进行数据分组
                        ArrayList<ArrayList<CallModel>> groups = new ArrayList<ArrayList<CallModel>>();

                        int numbers = callModels.size() / 50; //整数倍
                        if (numbers > 0) {
                            for (int i = 0; i < numbers; i++) {
                                int offset = i * 50;
                                ArrayList<CallModel> group = new ArrayList<>();
                                for (int j = offset; j < offset + 50; j++) {
                                    group.add(callModels.get(j));
                                }
                                groups.add(group);
                            }
                        }

                        int count = callModels.size() % 50; //取余
                        if (count > 0) {
                            ArrayList<CallModel> group = new ArrayList<>();
                            for (int i = callModels.size() - count; i < callModels.size(); i++) {//把最后一组也组装装起来
                                group.add(callModels.get(i));
                            }
                            groups.add(group);
                        }

                        taskCount = numbers + count > 0 ? 1 : 0;
                        if(taskCount == 0){
                            ScanCallLogUtils.flag = false;
                        }

                        NetLog.d("通话记录总共可分为"+groups.size()+"组");
                        return Observable.fromIterable(groups);
                    }
                })
                .observeOn(Schedulers.io())
                .flatMap(new Function<ArrayList<CallModel>, ObservableSource<BaseResponse<Object>>>() {
                    @Override
                    public ObservableSource<BaseResponse<Object>> apply(ArrayList<CallModel> callModels) throws Exception {
                        //开始上传通话记录
                        HashMap<String, String> map = new HashMap<>();
                        String json = new Gson().toJson(callModels);
                        map.put("record", json);
                        return OkHttpUtils.getInstance().getApi().postCallLogs(map);
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe(new Observer<BaseResponse<Object>>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(BaseResponse<Object> value) {
                        NetLog.d("通话记录同步结果: " + value.isSuccess() + ",当前线程 " + Thread.currentThread().getName());
                    }

                    @Override
                    public void onError(Throwable e) {
                        e.printStackTrace();
                    }

                    @Override
                    public void onComplete() {
                        flag = false;
                        taskCount = 0;
                        count = 0;
                        NetLog.d("scanCall 全部任务执行完成");
                    }
                });
    }

    /**
     * 扫描通话记录
     *
     * @param context
     */
    public static List<CallModel> startScanCallLogs(Context context) {
        if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED) {
            return new ArrayList<>();
        }

        Cursor cursor = context.getContentResolver().query(CallLog.Calls.CONTENT_URI, // 查询通话记录的URI
                columns
                , null, null, CallLog.Calls.DEFAULT_SORT_ORDER// 按照时间逆序排列，最近打的最先显示
        );
        List<CallModel> result = new ArrayList();
        //通过Cursor获得数据
        while (cursor.moveToNext()) {
            String name = cursor.getString(cursor.getColumnIndex(CallLog.Calls.CACHED_NAME));
            String number = cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER));
            long dateLong = cursor.getLong(cursor.getColumnIndex(CallLog.Calls.DATE));
            int duration = cursor.getInt(cursor.getColumnIndex(CallLog.Calls.DURATION));
            int type = cursor.getInt(cursor.getColumnIndex(CallLog.Calls.TYPE));
            int callType = 3;
            switch (type) {
                case CallLog.Calls.INCOMING_TYPE:
                    //"打入"
                    callType = 1;
                    break;
                case CallLog.Calls.OUTGOING_TYPE:
                    //"打出"
                    callType = 0;
                    break;
                case CallLog.Calls.MISSED_TYPE:
                    //"未接"
                    callType = 2;
                    break;
                default:
                    break;
            }
            CallModel callModel = new CallModel(name, number, dateLong, duration, callType);
            result.add(callModel);
        }
        cursor.close();
        return result;
    }
}
